﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using SpecF.Reporting;
using System.Linq.Expressions;

namespace SpecF
{
    public static class SpecFExtensions
    {
        public static Next<T> Next<T>(this SpecF<T> spec, Expression<Func<T, bool>> expression)
        {
            return SpecF<T>.When(expression);
        }

        public static SpecF<T> ExecWithoutReport<T>(this SpecF<T> specF, params T[] targets)
        {
            specF.ReportInternal(ReporterType.Console);
            ExecuteInternal(specF, targets, false);
            return specF;
        }

        public static SpecF<T> ExecWithConsoleReport<T>(this SpecF<T> specF, params T[] targets)
        {
            specF.ReportInternal(ReporterType.Console);
            ExecuteInternal(specF, targets);
            return specF;
        }       

        public static SpecF<T> ExecWithHtmlReport<T>(this SpecF<T> specF, params T[] targets)
        {
            specF.ReportInternal(ReporterType.Html);
            ExecuteInternal(specF, targets);
            return specF;
        }

        private static void ExecuteInternal<T>(SpecF<T> specF, T[] targets, bool doReport = true)
        {
            SpecF<T>.Specs.ForEach(delegate(SpecF<T> spec)
            {
                spec.Conditions.ForEach(delegate(Next<T> instruction)
                {
                    if (doReport)
                        specF.Reporter.Report(specF.SpecOwner.Name, instruction.ExpressionInfromatiom);

                    targets.Where(instruction.Check.Compile()).ToList<T>().ForEach(delegate(T target)
                    {
                        instruction.Events.ToList<Action<T>>().ForEach(delegate(Action<T> action)
                        {
                            action(target);
                        });
                    });
                });
            });
        }
    }
}